﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Teris
{
    enum E_Change_Type
    { 
        Left,Right
    }


    /// <summary>
    /// 记录所有方块形状的工厂
    /// </summary>
    internal class BlockWorker:IDraw
    {
        //储存所有需要绘制的方块
        List<DrawObject> blocks;

        //记录所有方块相对位置信息
        Dictionary<E_DrawType, BlockInfo> blockDic;
        BlockInfo curBlockInfo;
        E_DrawType curDrawType;
        int shapeIndex;
        public BlockWorker()
        {
            blockDic = new Dictionary<E_DrawType, BlockInfo>()
            {
                {E_DrawType.Cube,new BlockInfo(E_DrawType.Cube)},
                {E_DrawType.Line,new BlockInfo(E_DrawType.Line)},
                {E_DrawType.Tank,new BlockInfo(E_DrawType.Tank)},
                {E_DrawType.Left_Stair,new BlockInfo(E_DrawType.Left_Stair)},
                {E_DrawType.Left_Long_Stair,new BlockInfo(E_DrawType.Left_Long_Stair)},
                {E_DrawType.Right_Stair,new BlockInfo(E_DrawType.Right_Stair)},
                {E_DrawType.Right_Long_Stair,new BlockInfo(E_DrawType.Right_Long_Stair)}
            };

            GetRandomType();

        }

        public void GetRandomType()
        {
            Clear();

            //获得随机样式
            Random r = new Random();
            E_DrawType t = (E_DrawType)r.Next(1, 8);
            curDrawType = t;

            //方块相对位置信息
            curBlockInfo = blockDic[curDrawType];

            //方块
            blocks = new List<DrawObject>()
            {
                new DrawObject(curDrawType),
                new DrawObject(curDrawType),
                new DrawObject(curDrawType),
                new DrawObject(curDrawType)
            };

            blocks[0].pos = new Position(24, -5);

            shapeIndex = r.Next(0, curBlockInfo.Count);

            for (int i = 0; i < curBlockInfo[shapeIndex].Length; i++)
            {
                blocks[i + 1].pos = blocks[0].pos + curBlockInfo[shapeIndex][i];
            }

           
        }

        #region 旋转方块
        public void ChangeShap(E_Change_Type changeDir,Map map)
        {
            if (!CanChange(changeDir, map)) return;

            //清空之前的占位
            Clear();
            //选择选择方向
            switch (changeDir)
            {
                case E_Change_Type.Left:
                    shapeIndex = (shapeIndex - 1 + curBlockInfo.Count) % curBlockInfo.Count;
                    break;
                case E_Change_Type.Right:
                    shapeIndex = (shapeIndex + 1) % curBlockInfo.Count;
                    break;
            }
            //重新计算位置
            for (int i = 0; i < curBlockInfo[shapeIndex].Length; i++)
            {
                blocks[i + 1].pos = blocks[0].pos + curBlockInfo[shapeIndex][i];
            }
            Draw();
        }

        private bool CanChange(E_Change_Type changeDir, Map map)
        {
            int tryIndex = shapeIndex;

            switch (changeDir)
            {
                case E_Change_Type.Left:
                    tryIndex = (tryIndex - 1 + curBlockInfo.Count) % curBlockInfo.Count;
                    break;
                case E_Change_Type.Right:
                    tryIndex = (tryIndex + 1) % curBlockInfo.Count;
                    break;
            }

            //if (blocks[0].pos.x < 2 || blocks[0].pos.x > Game.w - 2 ||
            //    blocks[0].pos.y < 0 || blocks[0].pos.y > Game.h - 6)
            //{
            //    return false;
            //}


            Position p;
            for (int i = 0; i < curBlockInfo[tryIndex].Length; i++)
            {
                p = blocks[0].pos + curBlockInfo[tryIndex][i];
                //判断是否和边界重合
                if (p.x < 2 || p.x >= Game.w - 2  || p.y >= Game.h - 6)
                {
                    return false;
                }
            }

            for (int i = 0; i < curBlockInfo[tryIndex].Length; i++)
            {
                p = blocks[0].pos + curBlockInfo[tryIndex][i];
                //判断是否和动态方块重合
                for (int j = 0; j < map.dynamicWalls.Count; j++)
                {
                    if (p == map.dynamicWalls[j].pos)
                    {
                        return false;
                    }
                }
            }


            return true;
        }
        #endregion

        #region 左右移动
        public void MoveRL(E_Change_Type type, Map map)
        {
            if (!CanMove(type, map)) return;

            Clear();
            Position movePos = new Position(type == E_Change_Type.Left ? -2 : 2, 0);
            for (int i = 0; i < blocks.Count; i++)
            {
                blocks[i].pos += movePos;
            }
            Draw();
        }

        private bool CanMove(E_Change_Type type, Map map)
        {
            Position p;
            Position movePos = new Position(type == E_Change_Type.Left ? -2: 2, 0);

            //与墙壁重合时，不可移动
            for (int i = 0; i < blocks.Count; i++)
            {
                p = blocks[i].pos + movePos;
                if (p.x < 2 || p.x >= Game.w-2)
                {
                    return false;
                }
            }

            //与动态砖重合时，不可移动
            for (int i = 0; i < blocks.Count; i++)
            {
                p = blocks[i].pos + movePos;
                for (int j = 0; j < map.dynamicWalls.Count; j++)
                {
                    if (p == map.dynamicWalls[j].pos)
                    {
                        return false;
                    }
                }
            }

            return true;
        }
        #endregion

        #region 自动移动

        public void AutoDown(Map map)
        {
            if (!CanDown(map)) return;

            Clear();

            for (int i = 0; i < blocks.Count; i++)
            {
                blocks[i].pos.y += 1;
            }

            Draw();
        }

        public bool CanDown(Map map)
        {

            Position p;
            Position movePos = new Position(0, 1);

            for (int i = 0; i < blocks.Count; i++)
            {
                p = blocks[i].pos + movePos;
                if (p.y >= Game.h - 6)
                {
                    //变成动态砖块
                    map.AddDynamicWall(blocks);
                    GetRandomType();
                    return false;
                }
            }

            for (int i = 0; i < blocks.Count; i++)
            {
                p = blocks[i].pos + movePos;
                for (int j = 0; j < map.dynamicWalls.Count; j++)
                {
                    if (p == map.dynamicWalls[j].pos)
                    {
                        //变成动态砖块
                        map.AddDynamicWall(blocks);
                        GetRandomType();
                        return false;
                    }
                }
            }

            return true;
        }


        #endregion

        public void Draw()
        {
            for (int i = 0; i < blocks.Count; i++)
            {
                blocks[i].Draw();
            }
        }

        void Clear()
        {
            for (int i = 0; blocks!=null&&i < blocks.Count; i++)
            {
                blocks[i].Clear();
            }
        }
    }
}
